package com.mall.service.authority.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mall.commons.common.CommonPage;
import com.mall.commons.common.CommonResult;
import com.mall.commons.exception.CustomException;
import com.mall.model.domain.*;
import com.mall.service.authority.mapper.RoleMapper;
import com.mall.service.authority.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author Pan Rundong
 * @Date 2023-03-12 11:50
 * @Desc 角色Service实现类
 */
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, UmsRole> implements RoleService {
    @Autowired
    private RoleMenuService roleMenuService;
    @Autowired
    private RolePermissionService rolePermissionService;
    @Autowired
    private RoleResourceService roleResourceService;
    @Autowired
    private MenuService menuService;
    @Autowired
    private ResourceService resourceService;

    /**
     * 给角色分配菜单
     *
     * @param menuIds
     * @param roleId
     * @return void
     * @Author Pan Rundong
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void allocMenu(List<Long> menuIds, Long roleId) {
        // 1.查询角色表是否存在，不存在报错
        UmsRole umsRole = this.getById(roleId);
        if (umsRole == null) {
            throw new CustomException("角色不存在");
        }

        // 2.检测Role-Menu表是否已存在对应关系，存在则先删除
        LambdaQueryWrapper<UmsRoleMenuRelation> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UmsRoleMenuRelation::getRoleId, roleId);
        queryWrapper.in(UmsRoleMenuRelation::getMenuId, menuIds);
        List<UmsRoleMenuRelation> roleMenuList = roleMenuService.list(queryWrapper);
        //判断是否存在
        if (roleMenuList.size() > 0) {
            //已存在对应关系，删除
            LambdaQueryWrapper<UmsRoleMenuRelation> deleteWrapper = new LambdaQueryWrapper<>();
            deleteWrapper.eq(UmsRoleMenuRelation::getRoleId, roleId);
            roleMenuService.remove(deleteWrapper);
        }

        // 3.设置添加List
        List<UmsRoleMenuRelation> addList = menuIds.stream().map((menuId) -> {
            // 新建对象
            UmsRoleMenuRelation relation = new UmsRoleMenuRelation();
            relation.setRoleId(roleId);
            relation.setMenuId(menuId);
            return relation;
        }).collect(Collectors.toList());

        // 4.添加
        roleMenuService.saveBatch(addList);
    }



    /**
     * 分页获取角色信息
     *
     * @param pageNum
     * @param pageSize
     * @param keyword
     * @return com.mall.commons.common.CommonPage<com.mall.model.domain.UmsRole>
     * @Author Pan Rundong
     */
    @Override
    public CommonPage<UmsRole> findByPage(Integer pageNum, Integer pageSize, String keyword) {
        // 1.新建page对象，传入参数
        Page<UmsRole> page = new Page<>(pageNum, pageSize);

        // 2.模糊查询
        LambdaQueryWrapper<UmsRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(keyword != null, UmsRole::getName, keyword);
        this.page(page, queryWrapper);

        // 3.封装返回Page
        CommonPage<UmsRole> commonPage = CommonPage.getPage(page);
        return commonPage;
    }

    /**
     * 修改角色状态
     *
     * @param id
     * @param status
     * @return void
     * @Author Pan Rundong
     */
    @Override
    public void updateStatus(Long id, Integer status) {
        UmsRole umsRole = new UmsRole();
        umsRole.setId(id);
        umsRole.setStatus(status);
        this.updateById(umsRole);
    }

    /**
     * 给角色分配资源
     *
     * @param resourceIds
     * @param roleId
     * @return void
     * @Author Pan Rundong
     */
    @Override
    public void allocResource(List<Long> resourceIds, Long roleId) {
        // 1.查询角色表是否存在，不存在报错
        UmsRole umsRole = this.getById(roleId);
        if (umsRole == null) {
            throw new CustomException("角色不存在");
        }

        // 2.检测Role-Resource表是否已存在对应关系，存在则先删除
        LambdaQueryWrapper<UmsRoleResourceRelation> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UmsRoleResourceRelation::getRoleId, roleId);
        queryWrapper.in(UmsRoleResourceRelation::getResourceId, resourceIds);
        List<UmsRoleResourceRelation> roleResourceList = roleResourceService.list(queryWrapper);
        //判断是否存在
        if (roleResourceList.size() > 0) {
            //已存在对应关系，删除
            LambdaQueryWrapper<UmsRoleResourceRelation> deleteWrapper = new LambdaQueryWrapper<>();
            deleteWrapper.eq(UmsRoleResourceRelation::getRoleId, roleId);
            roleResourceService.remove(deleteWrapper);
        }

        // 3.设置添加List
        List<UmsRoleResourceRelation> addList = resourceIds.stream().map((resourceId) -> {
            // 新建对象
            UmsRoleResourceRelation relation = new UmsRoleResourceRelation();
            relation.setRoleId(roleId);
            relation.setResourceId(resourceId);
            return relation;
        }).collect(Collectors.toList());

        // 4.添加
        roleResourceService.saveBatch(addList);
    }

    /**
     * 添加角色
     *
     * @param umsRole
     * @return java.lang.Boolean
     * @Author Pan Rundong
     */
    @Override
    public Boolean checkAndSave(UmsRole umsRole) {
        // 1.设置条件查询是否存在同名
        LambdaQueryWrapper<UmsRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UmsRole::getName, umsRole.getName());
        UmsRole role = this.getOne(queryWrapper);

        // 2.判断，不存在则保存
        if (role == null) {
            this.save(umsRole);
            return true;
        } else {
            return false;
        }
    }

    /**
     * 更新角色
     *
     * @param umsRole
     * @return java.lang.Boolean
     * @Author Pan Rundong
     */
    @Override
    public Boolean checkAndUpdate(Long id, UmsRole umsRole) {
        // 1.设置条件查询是否存在同名
        UmsRole role = this.getById(id);
        // 2.判断，不存在则保存
        if (role != null) {
            this.updateById(umsRole);
            return true;
        } else {
            return false;
        }
    }

    /**
     * 批量删除角色
     *
     * @param ids
     * @return void
     * @Author Pan Rundong
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public CommonResult<String> deleteByIds(List<Long> ids) {
        // 1.删本体，判断是否禁用，禁用才能删
        LambdaQueryWrapper<UmsRole> umsRoleLambdaQueryWrapper = new LambdaQueryWrapper<>();
        umsRoleLambdaQueryWrapper.eq(UmsRole::getStatus, 0);
        umsRoleLambdaQueryWrapper.in(UmsRole::getId, ids);
        List<UmsRole> list = this.list(umsRoleLambdaQueryWrapper);
        if (list.size() == 0) {
            return CommonResult.error("删除失败");
        }

        this.remove(umsRoleLambdaQueryWrapper);

        // 2.查Role-Menu表，删对应
        LambdaQueryWrapper<UmsRoleMenuRelation> roleMenuQueryWrapper = new LambdaQueryWrapper<>();
        roleMenuQueryWrapper.in(UmsRoleMenuRelation::getRoleId, ids);
        roleMenuService.remove(roleMenuQueryWrapper);

        // 3.查Role-permission表，删对应
        LambdaQueryWrapper<UmsRolePermissionRelation> rolePermissionQueryWrapper = new LambdaQueryWrapper<>();
        rolePermissionQueryWrapper.in(UmsRolePermissionRelation::getRoleId, ids);
        rolePermissionService.remove(rolePermissionQueryWrapper);

        // 4.查Role-resource，删对应
        LambdaQueryWrapper<UmsRoleResourceRelation> roleResourceQueryWrapper = new LambdaQueryWrapper<>();
        roleResourceQueryWrapper.in(UmsRoleResourceRelation::getRoleId, ids);
        roleResourceService.remove(roleResourceQueryWrapper);
        return CommonResult.success(null, "删除成功");
    }

    /**
     * 根据Id查询用户菜单
     *
     * @param roleId
     * @return java.util.List<com.mall.model.domain.UmsMenu>
     * @Author Pan Rundong
     */
    @Override
    public List<UmsMenu> listMenu(Long roleId) {
        // 1.通过用户Id查询role-menu表获取对应菜单id
        LambdaQueryWrapper<UmsRoleMenuRelation> roleQueryWrapper = new LambdaQueryWrapper<>();
        roleQueryWrapper.eq(UmsRoleMenuRelation::getRoleId, roleId);
        List<UmsRoleMenuRelation> roleMenuRelations = roleMenuService.list(roleQueryWrapper);

        List<Long> menuIds = roleMenuRelations.stream().map(roleMenu-> roleMenu.getMenuId()).
                collect(Collectors.toList());

        // 2.通过menuIds获取对应menu
        LambdaQueryWrapper<UmsMenu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(UmsMenu::getId, menuIds);
        List<UmsMenu> umsMenus = menuService.list(queryWrapper);

        // 3.返回
        return umsMenus;
    }

    /**
     * 根据id获取后台资源
     *
     * @param roleId
     * @return java.util.List<com.mall.model.domain.UmsResource>
     * @Author Pan Rundong
     */
    @Override
    public List<UmsResource> listResource(Long roleId) {
        // 1.通过用户Id查询role-Resource表获取对应菜单id
        LambdaQueryWrapper<UmsRoleResourceRelation> roleQueryWrapper = new LambdaQueryWrapper<>();
        roleQueryWrapper.eq(UmsRoleResourceRelation::getRoleId, roleId);
        List<UmsRoleResourceRelation> roleResourceRelations = roleResourceService.list(roleQueryWrapper);

        List<Long> menuIds = roleResourceRelations.stream().map(roleResource-> roleResource.getResourceId()).
                collect(Collectors.toList());

        // 2.通过menuIds获取对应menu
        LambdaQueryWrapper<UmsResource> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(UmsResource::getId, menuIds);
        List<UmsResource> umsResources = resourceService.list(queryWrapper);

        // 3.返回
        return umsResources;
    }
}
